
package l1j.server.server.clientpackets;
import java.util.logging.Level;
import java.util.logging.Logger;

import static l1j.server.server.model.skill.L1SkillId.AREA_OF_SILENCE;
import static l1j.server.server.model.skill.L1SkillId.SILENCE;
import static l1j.server.server.model.skill.L1SkillId.STATUS_POISON_SILENCE;
import static l1j.server.server.model.skill.L1SkillId.STATUS_CHAT_PROHIBITED;
import static l1j.server.server.model.skill.L1SkillId.解卡點延遲;
import l1j.opqlo.NewSystem.ChatLog;
import l1j.opqlo.NewSystem.L1AI_Check;
import l1j.opqlo.NewSystem.change_name;
import l1j.opqlo.NewSystem.Extension.TreasureMaster;
import l1j.opqlo.NewSystem.Extension.FireRoom.FireRoomThread;
import l1j.opqlo.Server.L1World.L1World;
import l1j.opqlo.Server.L1World.WorldClan;
import l1j.server.Config;
import l1j.server.echo.ClientThread;
import l1j.server.server.GMCommands;
import l1j.server.server.model.L1Clan;
import l1j.server.server.model.L1Object;
import l1j.server.server.model.L1Teleport;
import l1j.server.server.model.Instance.L1MonsterInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_ChatPacket;
import l1j.server.server.serverpackets.S_NpcChatPacket;
import l1j.server.server.serverpackets.S_Paralysis;
import l1j.server.server.serverpackets.S_ServerMessage;
import l1j.server.server.serverpackets.S_SystemMessage;
import l1j.server.server.serverpackets.ServerBasePacket;


/**
 * 處理收到由客戶端傳來的聊天封包
 */
public class C_Chat extends ClientBasePacket {

	private static final String C_CHAT = "[C] C_Chat";
	private static final Logger _log = Logger.getLogger(C_Chat.class.getName());
	private boolean _isLog = true;

	/**一般竊聽**/
	private static final String _Normal = "\\fX【一般】";

	/**血盟竊聽**/
	private static final String _Clan = "\\fS【血盟】";


	/**組隊竊聽**/
	private static final String _Party ="\\fR【隊伍】";


	@Override
	public void start(final byte[] decrypt, final ClientThread client) {
		try {
			// 資料載入
			this.read(decrypt);

			final L1PcInstance pc = client.getActiveChar();

			if (pc == null) {
				return;
			}
			if(pc.isInHell()){
				pc.sendPackets(new S_ServerMessage(242)); // 現在チャット禁止中です。
				return;
			}
			if(pc._inFighting ==1 || pc._inFighting==3){
				pc.sendPackets(new S_ServerMessage(242)); // 現在チャット禁止中です。
				return;
			}
			final int chatType = this.readC();
			String chatText = this.readS();
			if(chatText == null){
				return;
			}
			//TODO 修正對話出現太長的字串會斷線
			if (chatText != null && chatText.length() > 130) {
				chatText = chatText.substring(0, 130);
			}
			//TODO 修正對話出現太長的字串會斷線

			if (pc.hasSkillEffect(SILENCE) || pc.hasSkillEffect(AREA_OF_SILENCE)
					|| pc.hasSkillEffect(STATUS_POISON_SILENCE) || pc.hasSkillEffect(STATUS_CHAT_PROHIBITED) ) {
				pc.sendPackets(new S_ServerMessage(242)); // 現在チャット禁止中です。
				return;
			}
			if(!pc.isGm() && pc.isInHell()){
				pc.sendPackets(new S_ServerMessage(242)); // 現在チャット禁止中です。
				return;
			}

			final String Name = pc.getName();
			final long time = System.currentTimeMillis();
			switch(chatType){
			case 0: // 一般頻道
				if (pc.isGhost()) {
					return;
				}
				_isLog = pc.checkLog(chatText);
				this.NormalChat(pc, chatText);
				break;

			case 2: //大喊
				if (pc.isGhost()) {
					return;
				}
				if(pc.大喊延遲 >=time){
					return;
				}
				//				if(pc.getMapId() == 1784){
				//					pc.sendPackets(new S_SystemMessage("這個地方無法大喊。"));
				//					pc.大喊延遲 = time+10000;
				//					return;
				//				}
				_isLog = pc.checkLog(chatText);
				this.PublicChat(pc, chatText);
				pc.大喊延遲 = time+10000;
				break;

			case 3: //全體廣播
				if (pc.isGm()|| pc.isMonitor()) {
					//					protected static final int S_OPCODE_GLOBALCHAT = 106;/** 廣播聊天頻道 */
					L1World.getInstance().broadcastPacketToAll(new S_ChatPacket(pc, chatText, 106,chatType));
					return;
				}
				if(pc.公頻延遲 >=time){
					return;
				}
				final byte[] Byte = chatText.getBytes();
				if(Byte == null){
					return;
				}
				if(!pc.checkGlobal(Byte)){
					return;
				}
				this.BraodChat(pc, chatText);
				if(!pc.isGm()){
					pc.公頻延遲 = time+10000;
				}
				break;
			case 4: //血盟頻道
				if (pc.getClanid() != 0) { // クラン所属中
					this.ClanChat(pc, chatText);
				}
				break;

			case 11: //組隊頻道
				if (pc.isInParty()) { // パーティー中
					this.PartyChat(pc, chatText);
				}
				break;

			case 12: //交易頻道
				if(pc.買賣延遲 >= time){
					return;
				}
				this.TradeChat(pc, chatText);
				pc.買賣延遲 = time + 10000;
				break;

			case 14: //隊伍聊天室
				if (pc.isInChatParty()) { // チャットパーティー中
					//					protected static final int S_OPCODE_NORMALCHAT = 35; 一般聊天頻道
					final S_ChatPacket s_chatpacket14 = new S_ChatPacket(pc, chatText,35, 14);
					final L1PcInstance[] partyMembers = pc.getChatParty().getMembers();
					for (final L1PcInstance listner : partyMembers) {
						if (!listner.getExcludingList().contains(pc.getId())&& !listner.isChangeName()) {
							listner.sendPackets(s_chatpacket14);
						}
					}
				}
				break;
			case 13://聯盟頻道
				chatType_13(pc , chatText);
				break;
				/*case 13: //聯盟頻道
				if (pc.getClanid() != 0) { // クラン所属中
					final L1Clan clan = L1World.getInstance().getClan(pc.getClanname());
					final int rank = pc.getClanRank();
					if (clan != null
							&& (rank == L1Clan.CLAN_RANK_GUARDIAN || rank == L1Clan.CLAN_RANK_PRINCE)) {
						final S_ChatPacket s_chatpacket13 = new S_ChatPacket(pc, chatText,Opcodes.S_OPCODE_GLOBALCHAT, 13);
						final L1PcInstance[] clanMembers = clan.getOnlineClanMember();

						// TODO 聯盟竊聽
						if (Config.GM_OVERHEARD13) {
							for (final L1PcInstance GM : L1World.getInstance().getAllGms()) {

								if(GM.isOverHead13()){//opqlo 竊聽開關
									if (GM.isGm() && pc.getId() != GM.getId()) {
										GM.sendPackets(new S_SystemMessage("\\fF【聯盟】" + Name + ":"+ chatText));

									}
								}
							}
						}
						for (final L1PcInstance listner : clanMembers) {
							final int listnerRank = listner.getClanRank();
							if (!listner.getExcludingList().contains(Name)
									&& (listnerRank == L1Clan.CLAN_RANK_GUARDIAN || listnerRank == L1Clan.CLAN_RANK_PRINCE)) {
								listner.sendPackets(s_chatpacket13);
							}
						}
					}
				}
				break;*/
				//15
			default:
				break;
			}
			if(chatType !=12 && chatType !=2 && chatType !=13){
				if(chatType == 0 && chatText.equalsIgnoreCase(".解卡點")){
					return;
				}
				if(_isLog){
					StringBuilder buff = new StringBuilder();
					buff.append(Name).append("	: ").append(chatText);
					ChatLog.get().setLog(client.getIp() ,chatType ,buff);
					buff.delete(0, buff.length());
					buff = null;
				}
				if (!pc.isGm()) {
					pc.checkChatInterval();
				}
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);

		} finally {
			this.over();
		}
	}






	/**世界頻道**/
	private void BraodChat(L1PcInstance pc , String chatText){
		//		if(pc.checkGlobal(chatText)){
		//		protected static final int S_OPCODE_GLOBALCHAT = 106;/** 廣播聊天頻道 */
		final S_ChatPacket s_chatpacket = new S_ChatPacket(pc,chatText, 106 ,3);
		for (final L1PcInstance listner : L1World.getInstance().getAllPlayers()) {
			if (!listner.getExcludingList().contains(pc.getId())) {
				// 拒絕接收廣播頻道
				if (!listner.isShowWorldChat()) {
					continue;
				}
				listner.sendPackets(s_chatpacket);
			}
		}
		//		}
	}

	/**血盟對話頻道**/
	private void ClanChat(L1PcInstance pc , String chatText){
		if (pc.getClanid() != 0) {
			final L1Clan clan = WorldClan.get().getClan(pc.getClanname());
			if(clan == null){
				return;
			}
			//			final int rank = pc.getClanRank();
			//			if (rank == L1Clan.CLAN_RANK_PUBLIC
			//					|| rank == L1Clan.CLAN_RANK_GUARDIAN
			//					|| rank == L1Clan.CLAN_RANK_PRINCE) {
			//			protected static final int S_OPCODE_GLOBALCHAT = 106;/** 廣播聊天頻道 */
			final S_ChatPacket s_chatpacket = new S_ChatPacket(pc, chatText,106, 4);
			final L1PcInstance[] clanMembers = clan.getOnlineClanMember();

			for (final L1PcInstance listner : clanMembers) {
				if (!listner.getExcludingList().contains(pc.getId())) {
					listner.sendPackets(s_chatpacket);
				}
			}
			this.sendClanToGM(pc , chatText);// TODO 血盟竊聽
		}
		//		}
	}



	@Override
	public String getType() {
		return C_CHAT;
	}

	/**一般頻道說話**/
	private void NormalChat(L1PcInstance pc ,  String chatText){
		// TODO 修正一般玩家輸入"."顯示指令錯誤套用1118版做修正
		try{
			if (chatText.startsWith(".")) {
				final String cmd = chatText.substring(1);
				if(cmd.isEmpty()){
					return;
				}
				/*if(cmd.equals("特效")){
			pc.setIsEffectOff();
			return;
			} */

				if(cmd.equalsIgnoreCase("解卡點")){
					if(pc.hasSkillEffect(解卡點延遲)){
						pc.sendPackets(new S_SystemMessage("5秒內只能使用一次。"));
						return;
					}
					pc.sendPackets(new S_Paralysis(S_Paralysis.TYPE_TELEPORT_UNLOCK, true));
					L1Teleport.teleportByMagic(pc, pc.getX(), pc.getY(), pc.getMapId(), pc.getHeading(), false); // 回到前一點
					pc.setSkillEffect(解卡點延遲, 5000);
					return;
				}

				if(cmd.equalsIgnoreCase("關電視")){
					if(pc.getConfig().isTVon()){
						pc.getConfig().setTV(1);
					}else{
						pc.getConfig().setTV(0);
					}
					pc.sendPackets(new S_SystemMessage("你【" + (pc.getConfig().isTVon() ==false? "關閉":"打開")+"】了電視牆。" ));
					return;
				}

				if(cmd.equalsIgnoreCase("回副本")){
					if (!pc.inQuestGame) {
						pc.sendPackets(new S_SystemMessage("您已死亡或沒有可進入的副本。"));
					}else if(!TreasureMaster.getInstance().ReJoinQuest2(pc)){
						FireRoomThread.get().reJoinRoom(pc);
					}
					return;
				}

				if(cmd.equalsIgnoreCase("參加活動")){
					if(Config.活動座標[2] !=0){
						L1Teleport.teleport(pc, Config.活動座標[0], Config.活動座標[1], (short)Config.活動座標[2], 0, false);
						if(Config.活動座標[2] == 5153){
							pc._inFighting = 1;
							if(pc.getParty()!=null){
								pc.getParty().leaveMember(pc);
							}
						}
					}else{
						pc.sendPackets(new S_SystemMessage("現在不是活動時間。" ));
					}
					return;
				}

				if (pc.isGm() || pc.isMonitor()){//opqlo GM指令修正
					GMCommands.getInstance().handleCommands(pc, cmd);
					return;
				}

			}else if (pc.isChangeName() && chatText.startsWith("新名稱")) {//opqlo 改名卡
				final String cmd = chatText.substring(3);
				change_name.getInstance().change(pc, cmd);
				return;
			}
			if(pc.getSuper()>0 ){
				if(chatText.startsWith("A")||chatText.startsWith("a")){//opqlo 掛機檢測系統
					final String cmd = chatText.substring(1);//final
					L1AI_Check.AI_CheckChat(pc, cmd);//opqlo 掛機檢測系統
					return;
				}
			}



			// トレードチャット
			// 本来はchatType==12になるはずだが、行頭の$が送信されない
			/*	if (chatText.startsWith("$")) {
			if(!pc.hasSkillEffect(交易頻延遲)){
				final String text = chatText.substring(1);
				TradeChat(pc, text);
				pc.setSkillEffect(交易頻延遲, 10000);
				if (!pc.isGm()) {
					pc.checkChatInterval();
				}
			}
			return;
		}*/
			//	protected static final int S_OPCODE_NORMALCHAT = 35; 一般聊天頻道
			final ServerBasePacket packets = new S_ChatPacket(pc, chatText,35, 0);

			if (!pc.getExcludingList().contains(pc.getId())) {
				pc.sendPackets(packets);
			}

			for (final L1PcInstance listner : L1World.getInstance().getRecognizePlayer(pc)) {
				if (!listner.getExcludingList().contains(pc.getId())) {
					listner.sendPackets(packets);
				}
			}
			this.sendNormalToGM(pc , chatText);// TODO 一般竊聽

			// 變形怪模仿說話處理
			for (final L1Object obj : pc.getKnownObjects()) {
				if (obj instanceof L1MonsterInstance) {
					final L1MonsterInstance mob = (L1MonsterInstance) obj;
					if (mob.getNpcTemplate().is_doppel() && mob.getName().equals(pc.getName())) {
						mob.broadcastPacketAll(new S_NpcChatPacket(mob, chatText,0));
					}
				}
			}
		}catch(final Exception e){
			_log.log(Level.SEVERE , e.getLocalizedMessage() , e);
		}
	}



	/**組隊對話頻道**/
	private void PartyChat(L1PcInstance pc , String chatText){
		//		protected static final int S_OPCODE_GLOBALCHAT = 106;/** 廣播聊天頻道 */
		final S_ChatPacket s_chatpacket = new S_ChatPacket(pc, chatText,106, 11);
		final L1PcInstance[] partyMembers = pc.getParty().getMembers();
		for (final L1PcInstance listner : partyMembers) {
			if (!listner.getExcludingList().contains(pc.getId())) {
				listner.sendPackets(s_chatpacket);
			}
		}
		this.sendPartyToGM(pc , chatText);// TODO 隊伍竊聽
	}
	/**大喊對話頻道**/
	private void PublicChat(L1PcInstance pc ,  String chatText){
		//	protected static final int S_OPCODE_NORMALCHAT = 35; 一般聊天頻道
		final S_ChatPacket s_chatpacket = new S_ChatPacket(pc, chatText,35, 2);
		if (!pc.getExcludingList().contains(pc.getId())) {
			pc.sendPackets(s_chatpacket);
		}
		for (final L1PcInstance listner : L1World.getInstance().getVisiblePlayer(pc, 50)) {
			if (!listner.getExcludingList().contains(pc.getId())) {
				listner.sendPackets(s_chatpacket);
			}
		}
		// 變形怪模仿說話處理
		for (final L1Object obj : pc.getKnownObjects()) {
			if (obj instanceof L1MonsterInstance) {
				final L1MonsterInstance mob = (L1MonsterInstance) obj;
				if (mob.getNpcTemplate().is_doppel()
						&& mob.getName().equals(pc.getName())) {
					for (final L1PcInstance listner : L1World.getInstance().getVisiblePlayer(mob, 50)) {
						listner.sendPackets(new S_NpcChatPacket(mob,chatText, 2));
					}
				}
			}
		}
	}

	private void sendClanToGM(final L1PcInstance pc , final String chatText){
		if(L1World.getInstance().getAllGms().isEmpty()){
			return;
		}
		final ServerBasePacket packets = new S_SystemMessage(_Clan + pc.getName() + ":" + chatText);
		for (final L1PcInstance GM : L1World.getInstance().getAllGms()) {
			if(GM.isOverHead4()){//opqlo 竊聽開關
				if (GM.isGm() && pc.getId() != GM.getId()) {
					GM.sendPackets(packets);
				}
			}
		}
	}
	private void sendNormalToGM(final L1PcInstance pc , final String chatText){
		if(L1World.getInstance().getAllGms().isEmpty()){
			return;
		}
		final ServerBasePacket packets = new S_SystemMessage(_Normal+ pc.getName() + ":" + chatText);
		for (final L1PcInstance GM : L1World.getInstance().getAllGms()) {
			if(GM.isOverHead0()){//opqlo 竊聽開關
				if (GM.isGm() && pc.getId() != GM.getId()) {
					GM.sendPackets(packets);
				}
			}
		}
	}

	private void sendPartyToGM(final L1PcInstance pc  , final String chatText){
		if(L1World.getInstance().getAllGms().isEmpty()){
			return;
		}
		final ServerBasePacket packets = new S_SystemMessage(_Party+ pc.getName() + ":" + chatText);
		if (Config.GM_OVERHEARD11) {
			for (final L1PcInstance GM : L1World.getInstance().getAllGms()) {
				if(GM.isOverHead11()){//opqlo 竊聽開關
					if (GM.isGm() && pc.getId() != GM.getId()) {
						GM.sendPackets(packets);
					}
				}

			}
		}
	}

	/*private void chatWorld(final L1PcInstance pc, final String chatText, final int chatType) {
		if (pc.isGm()|| pc.isMonitor()) {
			L1World.getInstance().broadcastPacketToAll(new S_ChatPacket(pc, chatText, Opcodes.S_OPCODE_GLOBALCHAT,chatType));
		} else if (pc.getLevel() >= Config.GLOBAL_CHAT_LEVEL) {
			if (L1World.getInstance().isWorldChatElabled()) {
				/*if (pc.get_food() >= 2) {
					if (Config.DeleteFood){//TODO 廣播不扣肉
						pc.set_food(pc.get_food() - 2);
					}*/
	//	pc.sendPackets(new S_PacketBox(S_PacketBox.FOOD, pc.get_food()));
	/*		for (final L1PcInstance listner : L1World.getInstance().getAllPlayers()) {
					if (!listner.getExcludingList().contains(pc.getId())) {
						if (listner.isShowTradeChat() && chatType == 12) {
							listner.sendPackets(new S_ChatPacket(pc,chatText, Opcodes.S_OPCODE_GLOBALCHAT,chatType));
						} else if (listner.isShowWorldChat()&& chatType == 3) {
							listner.sendPackets(new S_ChatPacket(pc,chatText, Opcodes.S_OPCODE_GLOBALCHAT,chatType));
						}
					}
				}
				//} else {
				//pc.sendPackets(new S_ServerMessage(462)); // \f1空腹のためチャットできません。
				//	}
			} else {
				pc.sendPackets(new S_ServerMessage(510)); // 現在ワールドチャットは停止中となっております。しばらくの間ご了承くださいませ。
			}
		} else {
			pc.sendPackets(new S_ServerMessage(195, String.valueOf(Config.GLOBAL_CHAT_LEVEL))); // レベル%0未満のキャラクターはチャットができません。
		}
	}*/

	/**
	 * 連盟頻道(%)
	 * @param pc
	 * @param chatText
	 */
	private void chatType_13(final L1PcInstance pc, final String chatText) {
		if (pc.getClanid() != 0) {
			final L1Clan clan = WorldClan.get().getClan(pc.getClanname());
			if (clan == null) {
				return;
			}
			switch (pc.getClanRank()) {
			case L1Clan.ALLIANCE_CLAN_RANK_GUARDIAN:// 6:守護騎士 
			case L1Clan.NORMAL_CLAN_RANK_GUARDIAN:// 9:守護騎士
			case L1Clan.CLAN_RANK_GUARDIAN:// 3:副君主 
			case L1Clan.CLAN_RANK_PRINCE:// 4:聯盟君主 
			case L1Clan.NORMAL_CLAN_RANK_PRINCE:// 10:聯盟君主
				//				final S_ChatClanUnion chatpacket = new S_ChatClanUnion(pc, chatText);
				final S_ChatPacket chatpacket = new S_ChatPacket(pc, chatText,106, 13);
				final L1PcInstance[] clanMembers = clan.getOnlineClanMember();
				// TODO 聯盟竊聽
				if (Config.GM_OVERHEARD13) {
					for (final L1PcInstance GM : L1World.getInstance().getAllGms()) {

						if(GM.isOverHead13()){//opqlo 竊聽開關
							if (GM.isGm() && pc.getId() != GM.getId()) {
								GM.sendPackets(new S_SystemMessage("\\fF【聯盟】" + pc.getName() + ":"+ chatText));

							}
						}
					}
				}
				for (final L1PcInstance listner : clanMembers) {
					if (!listner.getExcludingList().contains(pc.getId())) {
						switch (listner.getClanRank()) {
						case L1Clan.ALLIANCE_CLAN_RANK_GUARDIAN:// 6:守護騎士 
						case L1Clan.NORMAL_CLAN_RANK_GUARDIAN:// 9:守護騎士
						case L1Clan.CLAN_RANK_GUARDIAN:// 3:副君主 
						case L1Clan.CLAN_RANK_PRINCE:// 4:聯盟君主 
						case L1Clan.NORMAL_CLAN_RANK_PRINCE:// 10:聯盟君主
							listner.sendPackets(chatpacket);
							break;
						}
					}
				}
				break;
			}
		}
	}

	/**交易頻道**/
	private void TradeChat(L1PcInstance pc , String chatText){

		//		protected static final int S_OPCODE_GLOBALCHAT = 106;/** 廣播聊天頻道 */
		final S_ChatPacket s_chatpacket = new S_ChatPacket(pc,chatText, 106 ,12);
		for (final L1PcInstance listner : L1World.getInstance().getAllPlayers()) {
			if (!listner.getExcludingList().contains(pc.getId())) {
				if (!listner.isShowTradeChat() ) {
					continue;
				}
				listner.sendPackets(s_chatpacket);
			}
		}
	}
}
